package com.main.controller;

import com.main.entity.Dept;
import com.main.entity.User;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.servlet.ModelAndView;

import java.util.Arrays;

/**
 * @author admin
 * @date 2019/05/20
 */
@Controller
@RequestMapping(value = "modelAttribute")
/*将Model中的属性名为user,和dept属性存放在HttpSession中*/
@SessionAttributes(types = {User.class, Dept.class}, value = {"user", "dept"})
public class ModelAttributeController {

    /*用此@ModelAttribute注解标注之后,当我们调用login的方法的时候，会首先调用userModel方法，我们把user对象放进Model或ModelMap中之后，会自动传递到login中，获取user对象*/
    @ModelAttribute
    public void userModel(String username, String password, Model model, ModelAndView modelAndView) {
        System.out.println("进入@ModelAttribute标记的方法");
        User user = new User();
        user.setUserName(username);
        user.setPassword(password);
        model.addAttribute("user", user);
        modelAndView.addObject("user", user);

    }

    /*请求地址为login，设置请求方法为post或get的才会调用此方法*/
    @RequestMapping(value = "/login", method = {RequestMethod.GET, RequestMethod.POST})
    public String login(Model model) {
        User user = (User) model.asMap().get("user");
        System.out.println("获取的User对象:" + user);
        return "modelAttribute";
    }

    /*请求地址为login1，设置请求方法为post或get的才会调用此方法*/
    @RequestMapping(value = "/login1", method = {RequestMethod.GET, RequestMethod.POST})
    public ModelAndView login(ModelAndView modelAndView) {
        /*获取模型数据*/
        User user = (User) modelAndView.getModel().get("user");
        modelAndView.addObject("user", user);
        System.out.println("获取的User对象:" + user);
        /*设置要跳转的视图*/
        modelAndView.setViewName("modelAttribute1");
        return modelAndView;
    }


    /*请求地址为login2，设置请求方法为post或get的才会调用此方法*/
    @RequestMapping(value = "/login2", method = {RequestMethod.GET, RequestMethod.POST})
    /*使用@RequestParam注解绑定前台传递的参数username和password,并且通过required=false设置为password为不必传，设置默认不传的时候密码为defaultpassword*/
    /*例如请求的是http://localhost:8080/modelAttribute/login2.action?username="123"则会通过@RequestParam的value值为username的进行映射给String的userName*/
    /*但是如果我们传了requried=true的但是为空，这是不报错的，知识有此参数没有值而已*/ public String login(@RequestParam(value = "username", required = true) String userName, @RequestParam(value = "password", required = false, defaultValue = "defaultpassword") String passWord) {
        System.out.println("获取的用户名为：" + userName + "密码为:" + passWord);
        return "modelAttribute2";
    }


    @RequestMapping(value = "/pathVariableTest/{userId}")
    /*如果@Pathvariable注解使用了默认的value则在绑定参数的时候，会默认绑定同名的参数userId身上，
    如果找不到，则无法映射绑定参数,报异常[com.main.controller.ModelAttributeController.pathVariableTest(java.lang.Integer,org.springframework.ui.Model)]; nested exception is java.lang.IllegalStateException: Could not find @PathVariable [userId] in @RequestMapping]*/ public String pathVariableTest(@PathVariable Integer userId, Model model) {
        System.out.println("获取的用户id为：" + userId);
        model.addAttribute("message", "获取的用户id为：" + userId);
        return "modelAttribute3";
    }

    @RequestMapping(value = "/requestHeaderTest")
    /*所请求的头文件必须包含Accept,因为requried默认为truem否则报错，或设置requried为false，之后获取的Accept会主动映射到accepts数组中去*/ public String requestHeaderTest(@RequestHeader(value = "Accept") String[] accepts, Model model) {
        System.out.println("获取的用户请求头accepts信息为：" + Arrays.toString(accepts));
        model.addAttribute("message", "获取的用户请求头accepts信息为：" + Arrays.toString(accepts));
        return "modelAttribute4";
    }

    @RequestMapping(value = "/cookieValueTest")
    /*所获取cooki必须包含JSESSIONID,因为requried默认为truem否则报错，或设置requried为false，之后获取的Accept会主动映射到accepts数组中去*/ public String cookieValueTest(@CookieValue(value = "JSESSIONID", defaultValue = "") String sessionId, Model model) {
        System.out.println("获取的cookie的session信息为：" + sessionId);
        model.addAttribute("message", "获取的cookie的session信息为：" + sessionId);
        return "modelAttribute5";
    }


    @RequestMapping(value = "/sessionAttributesTest")
    /*获取前台传递的username，和deptname，使用required = false设置为并非含有此字段，分别赋值给userName和deptName*/ public String sessionAttributesTest(@RequestParam(value = "username", required = false) String userName, @RequestParam(value = "deptname", required = false) String deptName, Model model) {
        System.out.println("使用@sessionAttributes将参数设置到session中");

        User user = new User();
        user.setUserName(userName);

        Dept dept = new Dept();
        dept.setDeptname(deptName);

        model.addAttribute("user", user);
        model.addAttribute("dept", dept);
        return "modelAttribute6";
    }


    /*---------------ModelAttribute的使用方式   Begin---------------*/

    @ModelAttribute(value = "username")
    /*首先ModelAttribute会先于请求方法调用，请求的username会寻找到(@RequestParam(value = "username")，然后username匹配，之后把username映射到userName中，同时自动把username添加到Model中去
     * 注意，这里存入Model中的属性值为username，并不是后面起的参数属性值：userName,*/ public String modelAttributeTest1(@RequestParam(value = "username") String userName) {
        System.out.println("modelAttributeTest中的username为(返回值为一个类String):" + userName);
        return userName;
    }


    @ModelAttribute(value = "username")
    /*首先ModelAttribute会先于请求方法调用，请求的username会寻找到(@RequestParam(value = "username")，然后username匹配，之后把username映射到userName中，
    同时手动把username添加到Model中去*/ public void modelAttributeTest2(@RequestParam(value = "username") String userName, Model model) {
        System.out.println("modelAttributeTest中的username为（返回值为void）:" + userName);
        model.addAttribute("username", userName);
    }


    @ModelAttribute(value = "username")
    /*首先ModelAttribute会先于请求方法调用，请求的username会寻找到(@RequestParam(value = "username")，然后username匹配，之后把username映射到userName中，
    同时手动把username添加到Model中去*/ public User modelAttributeTest3(@RequestParam(value = "username") String userName) {
        System.out.println("modelAttributeTest中的username为（返回值为void）:" + userName);
        User user = new User();
        user.setUserName(userName);
        /*返回的时候，属性默认为实体类首字母小写如User返回的key为user，值为user这个对象*/
        return user;
    }


    /*请求地址为modelAttribute7，设置请求方法为post或get的才会调用此方法*/
    @RequestMapping(value = "modelAttribute7", method = {RequestMethod.GET, RequestMethod.POST})
    @ModelAttribute(value = "username")
    /*首先ModelAttribute会先于请求方法调用，请求的username会寻找到(@RequestParam(value = "username")，然后username匹配，之后把username映射到userName中，
    同时自动把username添加到Model中去*/ public String modelAttributeTest4(@RequestParam(value = "username") String userName) {
        System.out.println("modelAttributeTest中的username为（返回值为void）:" + userName);
        /*注意还是首先执行的是@ModelAttribute注解，只是相当于两个方法重复了，一样，所以先执行ModelAttribute标志的方法，请求的username参数映射之后返回username的值，也就是相当于request内部封装了username=username[不固定前台传过来的值]，然后再执行RequestMapping的方法进行页面跳转*/
        /*但是值得注意的是，此时跳转的是当前路径的../modelAttribute7.jsp页面而不是返回的userName的页面，这要特此注意*/
        return userName;
    }




    /*---------------ModelAttribute的使用方式   End---------------*/

}
